package com.zhihaoliang.map.details

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.annotation.VisibleForTesting
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.viewmodel.compose.viewModel
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.MapView
import com.amap.api.maps.MapsInitializer
import com.amap.api.maps.model.CameraPosition
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.MarkerOptions
import com.zhihaoliang.map.data.ExploreModel
import com.zhihaoliang.map.ui.theme.CraneTheme
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch

/**
 * @author 支豪亮
 * @date 2023/1/12 11:23
 * @des 详细的信息
 */

internal const val KEY_ARG_DETAILS_CITY_NAME = "KEY_ARG_DETAILS_CITY_NAME"

fun launchDetailsActivity(context: Context, item: ExploreModel) {
    context.startActivity(createDetailsActivityIntent(context, item))
}

@VisibleForTesting
fun createDetailsActivityIntent(context: Context, item: ExploreModel): Intent {
    val intent = Intent(context, DetailsActivity::class.java)
    intent.putExtra(KEY_ARG_DETAILS_CITY_NAME, item.city.name)
    return intent
}


@AndroidEntryPoint class DetailsActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        MapsInitializer.updatePrivacyShow(this, true, true)
        MapsInitializer.updatePrivacyAgree(this, true)
        setContent {
            CraneTheme {
                Surface {
                    DetailsScreen { finish() }
                }
            }
        }
    }
}

data class DetailsUiState(
    val cityDetails: ExploreModel? = null,
    val isLoading: Boolean = false,
    val throwError: Boolean = false
)

@Composable
fun DetailsScreen(onErrorLoading: () -> Unit) {
    val viewModel: DetailsViewModel = viewModel()
    val uiState by produceState(initialValue = DetailsUiState(isLoading = true)) {
        val cityDetailsResult = viewModel.cityDetails
        value = if (cityDetailsResult is com.zhihaoliang.map.base.Result.Success<ExploreModel>) {
            DetailsUiState(cityDetailsResult.data)
        } else {
            DetailsUiState(throwError = true)
        }
    }

    when {
        uiState.cityDetails != null -> {
            DetailsContent(uiState.cityDetails!!, Modifier.fillMaxSize())
        }
        uiState.isLoading -> {
            Box(modifier = Modifier.fillMaxWidth()) {
                CircularProgressIndicator(
                    color = MaterialTheme.colors.onSurface,
                    modifier = Modifier.align(Alignment.Center)
                )
            }
        }
        else -> {
            onErrorLoading()
        }
    }

}

@Composable
private fun DetailsContent(
    exploreModel: ExploreModel, modifier: Modifier = Modifier
) {
    Column(modifier = modifier, verticalArrangement = Arrangement.Center) {
        Spacer(modifier = Modifier.height(32.dp))

        Text(
            text = exploreModel.city.nameToDisplay,
            modifier = Modifier.align(Alignment.CenterHorizontally),
            style = MaterialTheme.typography.h4,
            textAlign = TextAlign.Center
        )

        Text(
            text = exploreModel.description,
            modifier = Modifier.align(Alignment.CenterHorizontally),
            style = MaterialTheme.typography.h6,
            textAlign = TextAlign.Center
        )

        Spacer(modifier = Modifier.height(16.dp))

        CityMapView(exploreModel)
    }
}

@Composable
private fun CityMapView(exploreModel: ExploreModel) {
    val mapView = rememberMapViewWithLifecycle()
    MapViewContainer(mapView = mapView, exploreModel = exploreModel)
}

@Composable
private fun MapViewContainer(mapView: MapView, exploreModel: ExploreModel) {
    val city = exploreModel.city
    val cameraPosition = remember(key1 = city.latitude, key2 = city.longitude) {
        LatLng(city.latitude.toDouble(), city.longitude.toDouble())
    }

    var zoom by rememberSaveable(mapView) { mutableStateOf(InitialZoom) }
    ZoomControls(zoom) {
        zoom = it.coerceIn(MinZoom, MaxZoom)
    }

    LaunchedEffect(key1 = mapView) {
        val aMap = mapView.map
        aMap.addMarker(MarkerOptions().position(cameraPosition).title(city.name))
    }

    val coroutineScope = rememberCoroutineScope()
    AndroidView({ mapView }) {
        coroutineScope.launch {
            val innerAMap = it.map
            val cameraUpdateInner = CameraUpdateFactory.newCameraPosition(
                CameraPosition(
                    cameraPosition, zoom, 30F, 30F
                )
            )
            innerAMap.moveCamera(cameraUpdateInner)
            innerAMap.uiSettings.isZoomControlsEnabled = false
        }
    }
}

@Composable
private fun ZoomControls(zoom: Float, onZoomChanged: (Float) -> Unit) {
    Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
        ZoomButton(text = "-") {
            onZoomChanged(zoom * 0.8F)
        }

        ZoomButton(text = "+") {
            onZoomChanged(zoom * 1.2F)
        }
    }
}

@Composable
private fun ZoomButton(text: String, onClick: () -> Unit) {
    Button(
        onClick = onClick, modifier = Modifier.padding(8.dp), colors = ButtonDefaults.buttonColors(
            backgroundColor = MaterialTheme.colors.onPrimary,
            contentColor = MaterialTheme.colors.onPrimary
        )
    ) {
        Text(text = text, style = MaterialTheme.typography.h5.copy(
            color = Color.Black
        ))
    }
}


private const val InitialZoom = 10f
const val MinZoom = 2f
const val MaxZoom = 30f